package com.uvnos4j.matilda.commons.utils;

import com.uvnos4j.matilda.commons.domain.AbstractTreeDomain;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * TreeUtils
 *
 * @author Guo.wl
 */
public class TreeUtil {

    /**
     * 两层循环实现建树
     *
     * @param treeNodes 传入的树节点列表
     * @return 树
     */
    public static <T extends AbstractTreeDomain> List<T> bulidTree(List<T> treeNodes) {
        List<T> trees = new ArrayList<>();
        for (T treeNode : treeNodes) {
            if (treeNode.isRoot()) {
                trees.add(treeNode);
            }

            for (T it : treeNodes) {
                if (treeNode.getId().equals(it.getParentId())) {
                    if (treeNode.getChildren() == null) {
                        treeNode.setChildren(new ArrayList<T>());
                    }
                    treeNode.getChildren().add(it);
                }
            }
        }
        return trees;
    }

    /**
     * 使用递归方法建树
     *
     * @param treeNodes 集合
     * @return 树
     */
    public static <T extends AbstractTreeDomain> List<T> bulidTreeByRecursive(List<T> treeNodes) {
        List<T> trees = new ArrayList<>();
        for (T treeNode : treeNodes) {
            if (treeNode.isRoot()) {
                trees.add(findChildren(treeNode, treeNodes));
            }
        }
        return trees;
    }

    /**
     * 递归查找子节点
     */
    private static <T extends AbstractTreeDomain> T findChildren(T parent, List<T> treeNodes) {
        for (T it : treeNodes) {
            if (parent.getId().equals(it.getParentId())) {
                if (parent.getChildren() == null) {
                    parent.setChildren(new ArrayList<>());
                }
                parent.getChildren().add(findChildren(it, treeNodes));
            }
        }
        return parent;
    }

    /**
     * TreeTable 组件排序。前提查询时先将列表按parent 和 sort排序
     *
     * @param sourceList 按parent 和 sort排序排序过的列表
     * @return 符合TreeTable排序要求的列表
     */
    public static <T extends AbstractTreeDomain> List<T> sortList(List<T> sourceList) {
        Map<Object, List<T>> map = new HashMap<>(16);
        for (T t : sourceList) {
            Object pid = t.getParentId();
            List<T> list = map.get(pid);
            if (list == null) {
                list = new ArrayList<>();
                map.put(pid, list);
            }
            list.add(t);
        }

        List<T> retList = new ArrayList<>();
        for (T node : sourceList) {
            if (node.isRoot()) {
                retList.add(node);
                // 如果子节点则继续追加它的子节点
                sortListByParent(map, retList, node);
            }
        }
        return retList;
    }

    /**
     * TreeTable 组件排序递归排序
     *
     * @param map     sourceList 按parent 和 sort排序排序过的列表
     * @param retList 要返回的列表
     * @param parent  父节点
     */
    private static <T extends AbstractTreeDomain> void sortListByParent(Map<Object, List<T>> map, List<T> retList, T parent) {
        List<T> list = map.get(parent.getId());
        if (list != null && list.size() > 0) {
            for (T node : list) {
                if (parent.getId().equals(node.getParentId())) {
                    retList.add(node);
                    sortListByParent(map, retList, node);
                }
            }
        }
    }

}